package org.wu.acw.server.infrastructure.persistence.schema;

import org.springframework.stereotype.Service;
import org.wu.framework.core.utils.ObjectUtils;
import org.wu.framework.lazy.orm.core.config.enums.LazyDataSourceType;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
import org.wu.framework.lazy.orm.database.lambda.dynamic.toolkit.DynamicLazyDSContextHolder;
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;
import org.wu.framework.lazy.orm.core.source.clickhouse.ClickHouseLazySchemata;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;
import org.wu.acw.core.domain.dto.DatabaseSchemaDto;
import org.wu.acw.core.domain.uo.AcwInstanceUo;
import org.wu.acw.core.domain.uo.AcwSchemaUo;
import org.wu.acw.server.domain.model.model.acw.schema.AcwSchema;
import org.wu.acw.server.domain.model.model.acw.schema.AcwSchemaRepository;
import org.wu.acw.server.infrastructure.converter.AcwSchemaConverter;
import org.wu.acw.server.infrastructure.entity.AcwInstanceDO;
import org.wu.acw.server.infrastructure.entity.AcwSchemaDO;

import java.util.List;

/**
 * describe :
 *
 * @author : Jia wei Wu
 * @version 1.0
 * @date : 2022/11/28 21:43
 */
@Service
public class ClickHouseSchemaRepository implements AcwSchemaRepository {
    private final LazyLambdaStream lazyLambdaStream;

    public ClickHouseSchemaRepository(LazyLambdaStream lazyLambdaStream) {
        this.lazyLambdaStream = lazyLambdaStream;
    }

    /**
     * 是否支持当前数据源类型
     *
     * @param lazyDataSourceType 数据源类型
     * @return 是否支持
     */
    @Override
    public boolean support(LazyDataSourceType lazyDataSourceType) {
        return LazyDataSourceType.CLICK_HOUSE.equals(lazyDataSourceType);
    }


    /**
     * describe 查询多个ACW 数据库库信息
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/10/24 03:15 下午
     **/

    @Override
    public Result<List<AcwSchema>> findListWithSize(AcwSchema acwSchema) {
        String instanceId = acwSchema.getInstanceId();
        Boolean initializeToLocal = acwSchema.getInitializeToLocal();
        if (!ObjectUtils.isEmpty(instanceId) && !ObjectUtils.isEmpty(initializeToLocal) && !initializeToLocal) {
            // 切换数据库
            String schemaName = acwSchema.getSchemaName();
            // 查询schema
            List<AcwSchema> acwSchemaList = lazyLambdaStream.selectList(
                    LazyWrappers.<ClickHouseLazySchemata>lambdaWrapper()
                            .like(!ObjectUtils.isEmpty(schemaName), ClickHouseLazySchemata::getSchemaName, schemaName + "%")
                            .notNull(ClickHouseLazySchemata::getSchemaName)
                            .orderByAsc(ClickHouseLazySchemata::getSchemaName)
                            .oas(instanceId, AcwSchema::getInstanceId)
                            .oas("false", AcwSchema::getInitializeToLocal)
                            .as(ClickHouseLazySchemata::getSchemaName, AcwSchema::getSchemaName)
                            .functionAs("(select concat( sum(round(  DATA_LENGTH / 1024 / 1024 , 2 )), 'M' ) from information_schema.tables where table_schema =schema_name )", AcwSchema::getDataLength)
                            .functionAs("(select concat( sum(round(  INDEX_LENGTH / 1024 / 1024 , 2 )), 'M' ) from information_schema.tables where table_schema =schema_name )", AcwSchema::getIndexLength)
                    ,
                    AcwSchema.class
            );
            DynamicLazyDSContextHolder.clear();
            return ResultFactory.successOf(acwSchemaList);
        }

        AcwSchemaDO acwSchemaDO = AcwSchemaConverter.INSTANCE.fromAcwSchema(acwSchema);
        List<AcwSchema> acwSchemaList = lazyLambdaStream
                .selectList(LazyWrappers.<AcwSchemaDO>lambdaWrapperBean(acwSchemaDO)
                                .leftJoin(LazyWrappers.<AcwSchemaDO, AcwInstanceDO>lambdaWrapperJoin()
                                        .eq(AcwSchemaDO::getInstanceId, AcwInstanceDO::getId))
                                .onlyUseAs()
                                .as(AcwSchema.class)
                        ,
                        AcwSchema.class);
        return ResultFactory.successOf(acwSchemaList);
    }

    /**
     * describe 分页查询多个ACW 数据库库信息
     *
     * @param
     * @return
     * @exception/throws
     * @author Jia wei Wu
     * @date 2023/10/24 03:15 下午
     **/

    @Override
    public Result<LazyPage<AcwSchema>> findPage(int size, int current, AcwSchema acwSchema) {
        String instanceId = acwSchema.getInstanceId();
        Boolean initializeToLocal = acwSchema.getInitializeToLocal();
        if (!ObjectUtils.isEmpty(instanceId) && !ObjectUtils.isEmpty(initializeToLocal) && !initializeToLocal) {
            // 切换数据库
            String schemaName = acwSchema.getSchemaName();
            LazyPage lazyPage = new LazyPage(current, size);
            // 查询schema
            LazyPage<AcwSchema> databaseSchemaUoLazyPage = lazyLambdaStream.selectPage(
                    LazyWrappers.<ClickHouseLazySchemata>lambdaWrapper()
                            .like(!ObjectUtils.isEmpty(schemaName), ClickHouseLazySchemata::getSchemaName, schemaName + "%")
                            .notNull(ClickHouseLazySchemata::getSchemaName)
                            .orderByAsc(ClickHouseLazySchemata::getSchemaName)
                            .oas(instanceId, AcwSchema::getInstanceId)
                            .oas("false", AcwSchema::getInitializeToLocal)
                            .as(ClickHouseLazySchemata::getSchemaName, AcwSchema::getSchemaName)
//                            .functionAs("(select concat( sum(round(  DATA_LENGTH / 1024 / 1024 , 2 )), 'M' ) from information_schema.tables where table_schema =schema_name )", AcwSchema::getDataLength)
//                            .functionAs("(select concat( sum(round(  INDEX_LENGTH / 1024 / 1024 , 2 )), 'M' ) from information_schema.tables where table_schema =schema_name )", AcwSchema::getIndexLength)

                    ,
                    lazyPage,
                    AcwSchema.class
            );
            return ResultFactory.successOf(databaseSchemaUoLazyPage);
        }

        AcwSchemaDO acwSchemaDO = AcwSchemaConverter.INSTANCE.fromAcwSchema(acwSchema);
        LazyPage<AcwSchema> lazyPage = new LazyPage<AcwSchema>(current, size);
        LazyPage<AcwSchema> resultLazyPage = lazyLambdaStream
                .selectPage(LazyWrappers.<AcwSchemaDO>lambdaWrapperBean(acwSchemaDO)
                                .leftJoin(LazyWrappers.<AcwSchemaDO, AcwInstanceDO>lambdaWrapperJoin()
                                        .eq(AcwSchemaDO::getInstanceId, AcwInstanceDO::getId))

                                .onlyUseAs()
                                .as(AcwSchemaUo.class)
                                .as(AcwInstanceUo::getInstanceName, DatabaseSchemaDto::getInstanceName)
                        , lazyPage,
                        AcwSchema.class);
        return ResultFactory.successOf(resultLazyPage);
    }


    /**
     * @param acwSchema schema 查询信息
     * @return {@link Result<List<AcwSchema>>}
     */
    @Override
    public Result<List<AcwSchema>> findList(AcwSchema acwSchema) {
        String instanceId = acwSchema.getInstanceId();
        Boolean initializeToLocal = acwSchema.getInitializeToLocal();
        if (!ObjectUtils.isEmpty(instanceId) && !ObjectUtils.isEmpty(initializeToLocal) && !initializeToLocal) {
            // 切换数据库
            String schemaName = acwSchema.getSchemaName();
            // 查询schema
            List<AcwSchema> acwSchemaList = lazyLambdaStream.selectList(
                    LazyWrappers.<ClickHouseLazySchemata>lambdaWrapper()
                            .like(!ObjectUtils.isEmpty(schemaName), ClickHouseLazySchemata::getSchemaName, schemaName + "%")
                            .notNull(ClickHouseLazySchemata::getSchemaName)
                            .orderByAsc(ClickHouseLazySchemata::getSchemaName)
                            .oas(instanceId, AcwSchema::getInstanceId)
                            .oas("false", AcwSchema::getInitializeToLocal)
                            .as(ClickHouseLazySchemata::getSchemaName, AcwSchema::getSchemaName)
                    ,
                    AcwSchema.class
            );
            DynamicLazyDSContextHolder.clear();
            return ResultFactory.successOf(acwSchemaList);
        }

        AcwSchemaDO acwSchemaDO = AcwSchemaConverter.INSTANCE.fromAcwSchema(acwSchema);
        List<AcwSchema> acwSchemaList = lazyLambdaStream
                .selectList(LazyWrappers.<AcwSchemaDO>lambdaWrapperBean(acwSchemaDO)
                                .leftJoin(LazyWrappers.<AcwSchemaDO, AcwInstanceDO>lambdaWrapperJoin()
                                        .eq(AcwSchemaDO::getInstanceId, AcwInstanceDO::getId))
                                .onlyUseAs()
                                .as(AcwSchema.class)
                        ,
                        AcwSchema.class);
        return ResultFactory.successOf(acwSchemaList);
    }
}
